/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package model.fibo;

import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Andrea
 */
public class FibonacciDB {

    private static List<Integer> numbers;
    private static final FiboDaemon daemon = new FiboDaemon();
    private static final FibonacciDB INSTANCE;

    static {
        INSTANCE = new FibonacciDB();
    }

    @SuppressWarnings("CallToThreadStartDuringObjectConstruction")
    private FibonacciDB() {
        numbers = new Stack<>();

        numbers.add(1);
        numbers.add(1);

        daemon.start();
    }

    public static boolean isFibonacciNumber(Integer num) {

        while (num.compareTo(numbers.get(numbers.size() - 1)) >= 1) {

            synchronized (daemon) {
                daemon.notify();
            }
        }
        
        return numbers.contains(num);
    }

    public static boolean isFibonacciNumber(Integer num1, Integer num2) {

        return isFibonacciNumber(num1 + num2);
    }

    public static Integer getFiboNumber(int i) {
        while (numbers.size() < i) {
            synchronized (daemon) {
                daemon.notify();
            }
        }

        return numbers.get(i);
    }

    private static class FiboDaemon extends Thread {

        public FiboDaemon() {
            super("fibo daemon");

            setDaemon(true);
        }

        @Override
        public void run() {
            synchronized (this) {
                while (true) {

                    for (int i = 0; i < 5; i++) {
                        numbers.add(numbers.get(numbers.size() - 1) + numbers.get(numbers.size() - 2));
                    }

                    try {
                        wait();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(FibonacciDB.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    }
}
